package cn.tedu.charging.order.job;

import cn.tedu.charging.order.dao.repository.OrderRepository;
import cn.tedu.charging.order.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.order.pojo.po.ChargingBillSuccessPO;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.Date;
import java.util.UUID;

/**
 * 设备自检延迟处理任务
 */
@Slf4j
public class DeviceCheckJob implements Job {

    /**
     * 必须需要无参的构造器
     * 如果没有 在初始化的时候 newInstance ,获取构造器 getConstructor0,获取失败
     * NoSuchMethodException 找不到方法异常 (找不到默认的构造器)
     */
    public DeviceCheckJob() {}

    public DeviceCheckJob(String orderNo,Integer gunId) throws Exception {
        log.debug("添加设备自检定时任务:订单号-{},枪id-{}",orderNo,gunId);
        //创建调度器工厂
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        //通过调度器工厂获取调度器
        Scheduler scheduler = schedulerFactory.getScheduler();

        //创建定时任务
        JobDetail jobDetail = JobBuilder.newJob(DeviceCheckJob.class)
                //定义定时任务的名称和组
                .withIdentity("DeviceCheckJob" + UUID.randomUUID(),"device_check_job")
                //传入订单号
                .usingJobData("orderNo",orderNo)
                //插入枪id
                .usingJobData("gunId",gunId)
                .build();

        //设备自检需要1分钟 模拟
        long deviceCheckTime = 1 * 60 * 1000;
        //当前时间
        long now = System.currentTimeMillis();
        //任务触发的时间
        Date triggerTime = new Date(now + deviceCheckTime);
        //创建触发器 并设置时间
        Trigger trigger = TriggerBuilder.newTrigger().startAt(triggerTime).build();

        //调度器 把 任务 和 触发器  绑定
        scheduler.scheduleJob(jobDetail,trigger);
        //启动调度器
        scheduler.start();
    }

    /**
     * 执行 干一些事情
     * @param context
     * @throws JobExecutionException
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.debug("设备自检任务开始执行:{}",context);
        //订单号从哪来?
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String orderNo = jobDataMap.getString("orderNo");
        Integer gunId = jobDataMap.getInt("gunId");
        //7. 判断是否有订单记录
        //8. 如果有成功订单记录 不用管 无需处理 无需处理 设备有响应,设备给订单服务发送了开始充电成功指令
        //9. 如果没有成功订单记录
        //10. 判断是否有失败订单记录   设备有响应,设备给订单服务发送了开始充电失败指令
        //11. 如果有失败订单记录  故障原因 设备故障-无法充电, 不用管,无需处理
        //12. 如果没有失败订单记录 插入失败订单记录  故障原因 设备无响应

        //DeviceCheckJob 没有在容器里, 可以通过 applicationContext  从容器获取 OrderRepository 实例
        OrderRepository orderRepository =
                SpringContextJobUtils.getBean("orderRepository", OrderRepository.class);

        //获取成功订单记录
        ChargingBillSuccessPO chargingBillSuccessPO = orderRepository.getSuccessOrder(orderNo);
        //7. 判断是否有订单记录
        if (chargingBillSuccessPO == null) {
            //9. 如果没有成功订单记录
            ChargingBillFailPO chargingBillFailPO = orderRepository.getFailOrder(orderNo);
            //10. 判断是否有失败订单记录
            if (chargingBillFailPO == null) {
                //12. 如果没有失败订单记录 插入失败订单记录  故障原因 设备无响应
                ChargingBillFailPO chargingBillFailPO1 = new ChargingBillFailPO();
                chargingBillFailPO1.setFailDesc("设备自检失败-设备无响应");
                chargingBillFailPO1.setBillId(orderNo);
                orderRepository.saveFailOrder(chargingBillFailPO1);
            }else {
                log.debug("设备自检失败-设备有响应,但是充不了电,这里逻辑无需修改 设备失败原因");
            }
        }else {
            log.debug("有成功订单记录,设备自检成功,有响应,能充电");
            log.debug("更新设备信息到订单表,枪id:{},订单编号:{},这里不是必须的操作,作为演示",gunId,orderNo);
            orderRepository.updateDeviceInfo(orderNo,gunId);
            log.debug("更新设备信息到订单表成功,枪id:{},订单编号:{},这里不是必须的操作,作为演示");
        }
    }
}
